<?php
declare(strict_types=1);

namespace app\common\service;

use app\model\tree\TreeSensitiveWordsModel;
use think\App;
use think\Service;

class TreeSensitiveFilterService extends Service
{
    protected string $cacheKey = 'tree_sensitive_words_pattern';
    public array $wordsData = [];

    public function __construct(App $app)
    {
        parent::__construct($app);
    }

    /**
     * 过滤敏感词主方法
     * @param int $unit_id 单位id
     * @param string $text
     * @return string
     */
    public function filter(int $unit_id, string $text): string
    {
        $pattern = $this->getCachedPattern($unit_id);
        return preg_replace_callback($pattern, function ($matches) {
            $this->wordsData[] = $matches[0];
            return str_repeat('*', mb_strlen($matches[0]));
        }, $text);
    }

    /**
     * 获取缓存的正则模式
     */
    protected function getCachedPattern(int $unit_id): string
    {
        return cache()->remember(env('REDIS_PROJECT').$this->cacheKey.$unit_id, function () use ($unit_id) {
            $TreeSensitiveWordsModel = new TreeSensitiveWordsModel();
            $words = $TreeSensitiveWordsModel->where([
                ['unit_id','=', $unit_id],
                ['status','=',1]
            ])->column('name');
            return $this->buildPattern($words);
        }, 3600);
    }

    /**
     * 构建正则表达式
     */
    protected function buildPattern(array $words): string
    {
        // 安全过滤与排序
        $words = array_unique(array_filter($words));
        usort($words, fn($a, $b) => mb_strlen($b) <=> mb_strlen($a));

        $escaped = array_map(fn($word) => preg_quote($this->normalizeWord($word), '/'), $words);

        return '/(' . implode('|', $escaped) . ')/ui';
    }

    /**
     * 标准化处理词汇
     */
    protected function normalizeWord(string $word): string
    {
        // 全角转半角、去空格、小写化
        $clean = mb_convert_kana(mb_convert_kana(trim($word), 'ASK'),'rn');
        return mb_strtolower($clean);
    }

    /**
     * 刷新缓存（供后台管理使用）
     */
    public function refreshCache(int $unit_id): void
    {
        cache()->delete(env('REDIS_PROJECT').$this->cacheKey.$unit_id);
        $this->getCachedPattern($unit_id);
    }

    /**
     * 更新词库（敏感词拦截次数）
     * @param int $unit_id
     * @param array $wordsData
     * @return void
     */
    public function updateLexicon(int $unit_id, array $wordsData): void
    {
        if (!empty($wordsData)){
            $TreeSensitiveWordsModel = new TreeSensitiveWordsModel();
            $TreeSensitiveWordsModel->where([
                ['unit_id','=', $unit_id],
                ['name','in', $wordsData],
                ['status','=',1]
            ])->inc('num')->save();
        }
    }
}
